#ifndef TextFormatter_First
#define TextFormatter_First
#ifdef __GNUG__
#pragma interface
#endif

#include "Font.h"
#include "Mark.h"

class Text;
class TextPainter;
class StaticTextView;

//---- LineDesc ----------------------------------------------------------------
//     descriptor of a text line

class LineDesc {
public:
	LineDesc();
	LineDesc(int b, int h= 0);
	void Reset();

	bool IsEqual(LineDesc l);
	void Max(Font *f);
	void Max(LineDesc ld);
	void Max(int ascent, int height);

	void FromFont(Font *f);
	int Height();
	int Base();
public:
	int lnAscent, lnHeight;
};

//---- LineMark ----------------------------------------------------------------

class LineMark: public Mark {
public:
	MetaDef(LineMark);
	LineMark(LineDesc ldesc, int pos= 0, int len= 0, eMarkState s= eStateNone);
	LineMark();
	void ChangeMark(int pos, int len, LineDesc ldesc, eMarkState s= eStateNone);
	void Copy(LineMark*);
	int Height();
	int Base();
	bool IsDifferent(LineMark *lm);

protected:
	LineDesc ld;
};

//---- TextFormatter -----------------------------------------------------------

class TextFormatter: public Object {
public:
	MetaDef(TextFormatter);
	TextFormatter();

	int Format(Text*, TextPainter *tp, int w, int from, int to);
	LineMark *LineAt(int i);
	static void Free();

protected:
	static LineMark **lines;
	static int nMarks;
	static int nLines;
	static int nAlloc;

	void AddBreak(Text*, TextPainter*, int from, int to, LineDesc &ld);
	virtual void DoFormat(Text*, TextPainter*, int w, int from, int to);
};

//---- SimpleFormatter, break lines only at breaking characters (\n, \r, \f) --

class SimpleFormatter: public TextFormatter {
public:
	MetaDef(SimpleFormatter);
	SimpleFormatter();

protected:
	void DoFormat(Text*, TextPainter*, int w, int from, int to);
};

//---- FoldingFormatter, fold lines (preemptive) -------------------------------

class FoldingFormatter: public TextFormatter {
public:
	MetaDef(FoldingFormatter);
	FoldingFormatter();

protected:
	void DoFormat(Text*, TextPainter*, int w, int from, int to);

	void BreakCharacter(Text*, TextPainter*, int at, LineDesc&, int w);
	void BreakWord(Text*, TextPainter*, LineDesc&, int w);
	void Break(TextPainter*, int from, int to, LineDesc&, int w);

private:
	Text *text;
	int start, end, width, nWords, wx, cx;
};

//---- abstract TextPager ------------------------------------------------------

class TextPager: public Object {
public:
	MetaDef(TextPager);
	TextPager();
	virtual Rectangle NextPageBreak(int, const Rectangle&, StaticTextView*);
	virtual void Repaginate(int startAt);
};

//---- abstract LinePager ------------------------------------------------------

class LinePager: public TextPager {
public:
	LinePager();
	Rectangle NextPageBreak(int, const Rectangle&, StaticTextView*);
};

inline bool LineDesc::IsEqual(LineDesc l)
	{ return lnAscent == l.lnAscent && lnHeight == l.lnHeight; }
inline int LineDesc::Height()
	{ return lnHeight; }
inline int LineDesc::Base()
	{ return lnAscent; }
inline int LineMark::Height()
	{ return ld.Height(); }
inline int LineMark::Base()
	{ return ld.Base(); }

#endif
